#include "TimerHeap.h"
#include"TcpConnection.h"
#include<algorithm>


TimerHeap::TimerHeap() {}
TimerHeap::~TimerHeap() {}

bool TimerHeap::cmp(TcpConnection* a, TcpConnection* b) {
    return a->expire_time > b->expire_time;
}

void TimerHeap::push(TcpConnection* conn) {
    conn->heap_index = heap.size();
    heap.push_back(conn);
    up(conn->heap_index);
}

void TimerHeap::remove(TcpConnection* conn) {
    size_t idx = conn->heap_index;
    if (idx >= heap.size()) return;
    std::swap(heap[idx], heap.back());
    heap[idx]->heap_index = idx;
    heap.pop_back();
    if (idx < heap.size()) {
        down(idx);
        up(idx);
    }
}

void TimerHeap::update(TcpConnection* conn, std::chrono::steady_clock::time_point new_expire) {
    conn->expire_time = new_expire;
    down(conn->heap_index);
    up(conn->heap_index);
}

TcpConnection* TimerHeap::top() {
    return heap.empty() ? nullptr : heap[0];
}

void TimerHeap::pop() {
    if (heap.empty()) return;
    remove(heap[0]);
}

bool TimerHeap::empty() const {
    return heap.empty();
}

size_t TimerHeap::size() const {
    return heap.size();
}

void TimerHeap::up(size_t idx) {
    while (idx > 0) {
        size_t parent = (idx - 1) / 2;
        if (!cmp(heap[parent], heap[idx])) break;
        std::swap(heap[parent], heap[idx]);
        heap[parent]->heap_index = parent;
        heap[idx]->heap_index = idx;
        idx = parent;
    }
}

void TimerHeap::down(size_t idx) {
    size_t n = heap.size();
    while (true) {
        size_t left = idx * 2 + 1, right = idx * 2 + 2, smallest = idx;
        if (left < n && cmp(heap[smallest], heap[left])) smallest = left;
        if (right < n && cmp(heap[smallest], heap[right])) smallest = right;
        if (smallest == idx) break;
        std::swap(heap[smallest], heap[idx]);
        heap[smallest]->heap_index = smallest;
        heap[idx]->heap_index = idx;
        idx = smallest;
    }
} 
